package obliczenia;

import ilog.concert.IloException;
import ilog.concert.IloLPMatrix;
import ilog.concert.IloMPModeler;
import ilog.concert.IloNumExpr;
import ilog.concert.IloNumVar;
import ilog.cplex.IloCplex;

import java.util.ArrayList;

public class Obliczenia {
	public String qPex(boolean czyOgraniczenie){
		String doZwrotu ="";
	try {
        IloCplex cplex = new IloCplex();
        IloLPMatrix lp = populateByRow(cplex, czyOgraniczenie);
        

        if ( cplex.solve() ) {
           double[] x     = cplex.getValues(lp);
           double[] dj    = cplex.getReducedCosts(lp);
           double[] pi    = cplex.getDuals(lp);
           double[] slack = cplex.getSlacks(lp);

           System.out.println("Solution status = " + cplex.getStatus());
           doZwrotu= doZwrotu + "Wartość rozwiązania  = " + cplex.getObjValue() + "\n";

           int nvars = x.length;
           for (int j = 0; j < nvars; ++j) {
              doZwrotu = doZwrotu + "Zmienna " + j+1 +
                                 ": Wartość = " + x[j] +
                                 " Zredukowany koszt = " + dj[j] + "\n";
           }

           int ncons = slack.length;
           for (int i = 0; i < ncons; ++i) {
              doZwrotu = doZwrotu + "Wartość " + i +
                                 ": x" +(i+1) + slack[i] + "\n";;
           }

           cplex.exportModel("qpex1.lp");
        }
        cplex.end();
     }
     catch (IloException e) {
        System.err.println("Concert exception '" + e + "' caught");
     }
	return doZwrotu;
  }

  static IloLPMatrix populateByRow(IloMPModeler model, boolean czyOgraniczenie) throws IloException {
     IloLPMatrix lp = model.addLPMatrix();

     double[]    lb = {0.0, 0.0, 0.0};
     double[]    ub = {100.0, 100.0, 100.0};
     IloNumVar[] x  = model.numVarArray(model.columnArray(lp, 3), lb, ub);

     // - x0 +   x1 + x2 <= 20
     //   x0 - 3*x1 + x2 <= 30
     double[]   lhs = {-Double.MAX_VALUE, -Double.MAX_VALUE};
     double[]   rhs = {6.0, 15.0};
     double[][] val = {{2.0,  3.0,  4.0},
                       { 3.0, 2.0,  10.0}};
     int[][]    ind = {{0, 1, 2},
                       {0, 1, 2}};
     double[]   lhs2 = {-Double.MAX_VALUE};
     double[]   rhs2 = {6.0};
     double[][] val2 = {{2.0,  3.0,  4.0}};
     int[][]    ind2 = {{0, 1, 2}};
     if(czyOgraniczenie){
    	 lp.addRows(lhs2, rhs2, ind2, val2); 
     }
     else{
         lp.addRows(lhs, rhs, ind, val);    	 
     }
     System.out.println(x[0] +" " + x[1] +" " + x[2]);
     // Q = 0.5 ( 33*x0*x0 + 22*x1*x1 + 11*x2*x2 - 12*x0*x1 - 23*x1*x2 )
     IloNumExpr x00 = model.prod( 3.0, x[0], x[0]);
     IloNumExpr x11 = model.prod( 4.0, x[1], x[1]);
     IloNumExpr x22 = model.prod( 5.0, x[2], x[2]);
     IloNumExpr x01 = model.prod( 2.0, x[0], x[1]);
     IloNumExpr x12 = model.prod( 2.0, x[1], x[2]);
     IloNumExpr x02 = model.prod( 4.0,  x[0], x[2]);
     IloNumExpr Q   = model.prod(0.5, model.sum(x00, x11, x22, x01, x12, x02));

     // maximize x0 + 2*x1 + 3*x2 + Q
     double[] objvals = {1.0, 1.0, 1.0};
     model.add(model.maximize(model.diff(model.scalProd(x, objvals), Q)));

     return (lp);
  }
}

	
